#include "Sprite.h"



Sprite::Sprite()
{
	/**
	Initialize class Sprite members
	*/

	VertexBuffer = NULL; //Set Buffer To NULL/Zero
	ColorBuffer  = NULL; //Set Buffer To NULL/Zero
	IndexBuffer  = NULL; //Set Buffer To NULL/Zero
	UseWire = false;
	texture = NULL;
	shader_test = NULL;


}

Sprite::~Sprite()
{
	/**
	Delete buffered data that directx was controlling
	*/

	shader_test = NULL;

	VertexBuffer->Release(); //Release/Delete Data
	ColorBuffer->Release();  //Release/Delete Data
	TextureBuffer->Release();//Release/Delete Data

	//if(shader_test != NULL)
		//delete shader_test;
}

void Sprite::init(LPDIRECT3DDEVICE9 d3ddev, b2World *world_physics)
{
	/**
	Build data and setup the buffers so that directx knows how to handle the data.
	*/

	//shader_test = new ShaderEffect();
	//shader_test->LoadEffect(d3ddev);

	display_name.init(d3ddev);
	display_name.setPointSize(12);

	this->world_physics = world_physics;

	if( d3ddev == NULL )
		_cprintf("d3ddev is NULL!\n");

	/////////////////////////////
	//Create Vertices and Color//
	//			Data		   //
	/////////////////////////////

	Vertex vertices [] = {//   x     y      z
							{-1.0, -1.0 ,  0.0},
							{-1.0,  1.0 ,  0.0},
							{ 1.0,  1.0 ,  0.0},
							{ 1.0, -1.0 ,  0.0}
						 };

	Color color [] = {//                       r    g    b    a     (red, green , blue, alpha)
						{D3DCOLOR_COLORVALUE( 1.0, 0.0, 0.0, 1.0 )},
						{D3DCOLOR_COLORVALUE( 0.0, 1.0, 0.0, 1.0 )},
						{D3DCOLOR_COLORVALUE( 0.0, 0.0, 1.0, 1.0 )},
						{D3DCOLOR_COLORVALUE( 1.0, 0.0, 1.0, 1.0 )}
					 };
	
	texcoords[0].u = 0.0f;
	texcoords[0].v = 0.0f;
	texcoords[1].u = 0.0f;
	texcoords[1].v = 1.0f;
	texcoords[2].u = 1.0f;
	texcoords[2].v = 1.0f;
	texcoords[3].u = 1.0f;
	texcoords[3].v = 0.0f;


	WORD indices [] = { 0, 1, 2, 
						0, 2, 3 };
						

	///////////////////////
	//Create VertexBuffer//
	///////////////////////

	if(FAILED(d3ddev->CreateVertexBuffer( 4*sizeof(Vertex),	  //Check to see if creating the vertex
										  D3DUSAGE_WRITEONLY, //buffer was a success.
										  0,
										  D3DPOOL_MANAGED, 
										  &VertexBuffer, 
										  NULL )))
	{
		_cprintf("%s\n", "falied to create vertex buffer!"); //Print tp console if failed
	}


	if(VertexBuffer == NULL)					  //Making sure VertexBuffer is not NULL/Zero
		_cprintf("%s\n", "VertexBuffer is NULL!");

    //locking VertexBuffer and load the vertices into it
    VertexBuffer->Lock(0, sizeof(vertices), (void**)&pVertices, 0);
    if( memcpy(pVertices, vertices, sizeof(vertices)) == NULL )
		_cprintf("MemCpy Failed!\n");
    VertexBuffer->Unlock();

	////////////////////////
	//Create TextureBuffer//
	////////////////////////

	if(FAILED(d3ddev->CreateVertexBuffer( 4*sizeof(TexCoord), //Check to see if creating the vertex
										  D3DUSAGE_WRITEONLY, //buffer was a success.
										  0,
										  D3DPOOL_MANAGED, 
										  &TextureBuffer, 
										  NULL )))
	{
		_cprintf("%s\n", "falied to create texture buffer!"); //Print tp console if failed
	}


	if(TextureBuffer == NULL)					  //Making sure VertexBuffer is not NULL/Zero
		_cprintf("%s\n", "VertexBuffer is NULL!");

    //locking TextureBuffer and load the vertices into it
	TextureBuffer->Lock(0, sizeof(texcoords), (void**)&pTexCoords, 0);
    if( memcpy(pTexCoords, texcoords, sizeof(texcoords)) == NULL )
		_cprintf("MemCpy Failed!\n");
    TextureBuffer->Unlock();

	//////////////////////
	//Create ColorBuffer//
	//////////////////////

	if(FAILED(d3ddev->CreateVertexBuffer( 4*sizeof(Color),    //Check to see if creating the color
										  D3DUSAGE_WRITEONLY, //buffer was a success.
										  0,
										  D3DPOOL_MANAGED, 
										  &ColorBuffer, 
										  NULL )))
	{
		_cprintf("%s\n", "falied to create color buffer!"); //Print tp console if failed
	}
 

	if(ColorBuffer == NULL)						 //Making sure ColorBuffer is not NULL/Zero
		_cprintf("%s\n", "ColorBuffer is NULL!");

    //locking ColorBuffer and load the color into it
    ColorBuffer->Lock(0, sizeof(color), (void**)&pColors, 0);
    if( memcpy(pColors, color, sizeof(color)) == NULL )
		_cprintf("MemCpy Failed!\n");
    ColorBuffer->Unlock();

	//////////////////////
	//Create IndexBuffer//
	//////////////////////

	if(FAILED(d3ddev->CreateIndexBuffer( 6*sizeof(WORD),    //Check to see if creating the color
										 D3DUSAGE_WRITEONLY,//buffer was a success.
										 D3DFMT_INDEX16,
										 D3DPOOL_MANAGED, 
										 &IndexBuffer, 
										 NULL )))
	{
		_cprintf("%s\n", "falied to create color buffer!"); //Print tp console if failed
	}
 

	if(IndexBuffer == NULL)						 //Making sure ColorBuffer is not NULL/Zero
		_cprintf("%s\n", "IndexBuffer is NULL!");

    //locking ColorBuffer and load the color into it
    IndexBuffer->Lock(0, sizeof(indices), (void**)&pIndex, 0);
    if( memcpy(pIndex, indices, sizeof(indices)) == NULL )
		_cprintf("MemCpy Failed!\n");
    IndexBuffer->Unlock();

	//////////////////////////////
	//Setup Element Declarations//
	//////////////////////////////

	D3DVERTEXELEMENT9 dwDecl[] = 
	{
		//  Stream  Offset         Type                   Method                 Usage          Usage Index       
		{     0,      0,    D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,     0      },
		{     1,      0,    D3DDECLTYPE_FLOAT2,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,     0      },
		//{     2,      0,    D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,        0      },
		D3DDECL_END()
	};

	//////////////////////////
	//Create the declaration//
	//////////////////////////
	d3ddev->CreateVertexDeclaration( dwDecl, &VertexDeclaration );
}

bool Sprite::FlipHorizontal()
{
	TexCoord tmp;

	tmp = texcoords[0];
	texcoords[0] = texcoords[3];
	texcoords[3] = tmp;

	tmp = texcoords[1];
	texcoords[1] = texcoords[2];
	texcoords[2] = tmp;
	
	if(TextureBuffer == NULL)					  //Making sure VertexBuffer is not NULL/Zero
	{
		_cprintf("%s\n", "TextureBuffer is NULL!");
		return 0;
	}

    //locking TextureBuffer and load the vertices into it
	TextureBuffer->Lock(0, sizeof(texcoords), (void**)&pTexCoords, 0);
    if( memcpy(pTexCoords, texcoords, sizeof(texcoords)) == NULL )
	{
		_cprintf("MemCpy Failed! -> FlipH TexCoords\n");
		return 0;
	}
    TextureBuffer->Unlock();

	return 1;
}

bool Sprite::ModifyTexCoords(TexCoord t[])
{
	/*
	TexCoord tmp;

	tmp = texcoords[0];
	texcoords[0] = texcoords[3];
	texcoords[3] = tmp;

	tmp = texcoords[1];
	texcoords[1] = texcoords[2];
	texcoords[2] = tmp;
	*/
	
	this->texcoords[0] = t[0];
	this->texcoords[1] = t[1];
	this->texcoords[2] = t[2];
	this->texcoords[3] = t[3];

	if(TextureBuffer == NULL)					  //Making sure VertexBuffer is not NULL/Zero
	{
		_cprintf("%s\n", "TextureBuffer is NULL!");
		return 0;
	}

    //locking TextureBuffer and load the vertices into it
	TextureBuffer->Lock(0, sizeof(texcoords), (void**)&pTexCoords, 0);
    if( memcpy(pTexCoords, texcoords, sizeof(texcoords)) == NULL )
	{
		_cprintf("MemCpy Failed! -> FlipH TexCoords\n");
		return 0;
	}
    TextureBuffer->Unlock();

	return 1;
}

bool Sprite::FlipVertical()
{
	TexCoord tmp;

	tmp = texcoords[0];
	texcoords[0] = texcoords[1];
	texcoords[1] = tmp;

	tmp = texcoords[2];
	texcoords[2] = texcoords[3];
	texcoords[3] = tmp;
	
	if(TextureBuffer == NULL)					  //Making sure VertexBuffer is not NULL/Zero
	{
		_cprintf("%s\n", "TextureBuffer is NULL!");
		return 0;
	}

    //locking TextureBuffer and load the vertices into it
	TextureBuffer->Lock(0, sizeof(texcoords), (void**)&pTexCoords, 0);
    if( memcpy(pTexCoords, texcoords, sizeof(texcoords)) == NULL )
	{
		_cprintf("MemCpy Failed! -> FlipV TexCoords\n");
		return 0;
	}
    TextureBuffer->Unlock();

	return 1;
}

void Sprite::WireMode(bool UseWire)
{
	/**
	Render the object as an outline or it's wire frame form.
	*/
	this->UseWire = UseWire;
}

void Sprite::SetShader(ShaderEffect * shader)
{
	shader_test = shader;
}

void Sprite::Render(LPDIRECT3DDEVICE9 d3ddev)
{
	/**
	Render a sprite (a 2D plane). Handle the movement and such. 
	*/
	D3DXMATRIXA16 matWorld;
	D3DXMATRIXA16 matTrans;
	D3DXMATRIXA16 matRot;
	D3DXMATRIXA16 matScale;

	
	
	//Check to see if the object has physics attributes.
	//If so then we translate according to what the physics library gives us.
	//If not then the position is set by default values or user input.

	if( phys_body != NULL )
	{
		D3DXMatrixTranslation( &matTrans, phys_body->GetPosition().x, phys_body->GetPosition().y, z-layer );
		D3DXMatrixScaling( &matScale, sx, sy, sz );
		D3DXMatrixRotationYawPitchRoll( &matRot, 
			                            D3DXToRadian(yaw), 
			                            D3DXToRadian(pitch), 
										phys_body->GetAngle() );
	}
	else
	{
		D3DXMatrixTranslation( &matTrans, x, y, z-layer );
		D3DXMatrixScaling( &matScale, sx, sy, sz );
		D3DXMatrixRotationYawPitchRoll( &matRot, 
			                            D3DXToRadian(yaw), 
			                            D3DXToRadian(pitch), 
			                            D3DXToRadian(roll) );
	}

	matWorld = matScale * matRot * matTrans * cameraMatrix;	//Multiple all the matrices so that the objects display on the screen correctly

	d3ddev->SetTransform( D3DTS_WORLD, &matWorld );			//Tell directx that we are modifying the world matrix

	D3DXMATRIXA16 v_mat;
	D3DXMATRIXA16 p_mat;

	d3ddev->GetTransform( D3DTS_VIEW, &v_mat);
	d3ddev->GetTransform( D3DTS_PROJECTION, &p_mat);

	D3DXMATRIXA16 a_mat = matWorld*v_mat*p_mat;

	if(shader_test != NULL)
	shader_test->setTestParam(a_mat, "gWVP");

	LPDIRECT3DVERTEXDECLARATION9 vdecl;
	d3ddev->GetVertexDeclaration(&vdecl);

    // select which vertex format we are using
	if( vdecl != VertexDeclaration )
		d3ddev->SetVertexDeclaration( VertexDeclaration );

	//Set The Index Buffer
	d3ddev->SetIndices( IndexBuffer );

    // select the vertex buffer to display
	d3ddev->SetStreamSource(0, VertexBuffer,   0, sizeof(Vertex));
	d3ddev->SetStreamSource(1, TextureBuffer , 0, sizeof(TexCoord));
	//d3ddev->SetStreamSource(2, ColorBuffer ,   0, sizeof(Color));

    // copy the vertex buffer to the back buffer


	if( texture != NULL)
	{
		if(shader_test != NULL)
		{
			shader_test->SetEffectTech("SimpleTech0");
			shader_test->SetEffectTex("gTex", texture);
		}
		else
			texture->UseTexture();
	}
	else
	{
		if(shader_test != NULL)
			shader_test->SetEffectTech("SimpleTech1");
		else
			d3ddev->SetTexture(0, 0);
	}

	if(shader_test != NULL)
		shader_test->UseEffect();

	if( !UseWire )
		d3ddev->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, 4,  0, 2 );
	else
	{
		//Draw the outline
		//ddev->DrawIndexedPrimitive( D3DPT_LINESTRIP, 0, 0, 4,  1, 1 );
		//d3ddev->DrawIndexedPrimitive( D3DPT_LINESTRIP, 0, 0, 4,  2, 1 );

		//d3ddev->DrawIndexedPrimitive( D3DPT_LINESTRIP, 0, 0, 4,  3, 1 );
		//d3ddev->DrawIndexedPrimitive( D3DPT_LINESTRIP, 0, 0, 4,  4, 1 );
		//d3ddev->DrawIndexedPrimitive( D3DPT_LINESTRIP, 0, 0, 4,  5, 1 );
	}

	if(shader_test != NULL)
		shader_test->StopEffect();

}